﻿using System;
using System.Collections.Generic;
using System.Windows.Forms;

using Pibby.Core;

namespace Pibby.Controls
{
	public class NavigationView : UserControl
	{
		public const int MediaPlayerImageIndex = 0;
		public const int NewEpisodesImageIndex = 1;
		public const int DownloadedEpisodesImageIndex = 2;
		public const int PodcastImageIndex = 3;
		public const int MediaPlayerContentImageIndex = 4;
		//public const int AllPodcastImageIndex = 1;
		//public const int PodcastImageIndex = 1;
		//public const int DeviceImageIndex = 3;

		// well-known ids
		private const string NewEpisodes = "{E8E102C8-5E3A-4670-B765-0922B541875F}";
		private const string DownloadedEpisodes = "{FA6BCBB0-54CB-48AB-BBDD-3F7D47635C61}";
		private const string MediaPlayer = "{424086BC-0E38-4FD5-9904-91FDA8E155F4}";
		private const string MediaPlayerContent = "{A25425D0-45F1-4119-AE05-18397865870C}";
		private TableLayoutPanel tableLayoutPanel1;
		private HeadedTree inboxTree;
		private HeadedTree deviceTree;
		private HeadedTree subscriptionTree;
		private const string Subscriptions = "{C8EBE217-1508-432A-87D8-ABFE44BD128C}";

		public event EventHandler NewEpisodesSelected;

		public event EventHandler DownloadsSelected;

		public event EventHandler DeviceSelected;

		public event EventHandler DeviceContentSelected;

		public event EventHandler SubscriptionsSelected;

		public event EventHandler<PodcastEventArgs> PodcastSelected;

		public NavigationView()
		{
			InitializeComponent();

			this.State = NavigationState.Unknown;
		}

		public virtual void Configure(ImageList images)
		{
			this.deviceTree.Configure("<b>Devices</b>", images);
			this.deviceTree.contentTree.NodeMouseClick += new TreeNodeMouseClickEventHandler(Device_NodeMouseClick);

			this.inboxTree.Configure("<b>Inbox</b>", images);
			this.inboxTree.contentTree.NodeMouseClick += new TreeNodeMouseClickEventHandler(Inbox_NodeMouseClick);

			this.subscriptionTree.Configure("<b>Subscription</b>", images);
			this.subscriptionTree.contentTree.NodeMouseClick += new TreeNodeMouseClickEventHandler(Subscription_NodeMouseClick);
		}

		void Device_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
		{
			var item = e.Node;

			if (item != null)
			{
				NodeTag id = item.Tag as NodeTag;

				if (id != null && !string.IsNullOrEmpty(id.Guid))
				{
					if (id.Guid == NavigationView.MediaPlayer)
					{
						this.State = NavigationState.MediaPlayer;
						this.DeviceSelected.Fire(this);
					}
					else if (id.Guid == NavigationView.MediaPlayerContent)
					{
						this.DeviceContentSelected.Fire(this);
					}
				}
			}
 		}

		void Inbox_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
		{
			var item = e.Node;

			if (item != null)
			{
				NodeTag id = item.Tag as NodeTag;

				if (id != null && !string.IsNullOrEmpty(id.Guid))
				{
					if (id.Guid == NavigationView.NewEpisodes)
					{
						this.NewEpisodesSelected.Fire(this);
					}
					else if (id.Guid == NavigationView.DownloadedEpisodes)
					{
						this.DownloadsSelected.Fire(this);
					}
				}
			}
		}

		void Subscription_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
		{
			var item = e.Node;

			if (item != null)
			{
				NodeTag id = item.Tag as NodeTag;

				if (id != null)
				{
					if (id.DbKey > 0)
					{
						// individual podcast ???
						this.State = NavigationState.Podcast;
						this.PodcastSelected.Fire(this, new PodcastEventArgs(id.DbKey));
					}
					else if (id.Guid == NavigationView.Subscriptions)
					{
						this.State = NavigationState.Subscription;
						this.SubscriptionsSelected.Fire(this);
					}
				}
			}
		}
		
		public void RefreshContent(IEnumerable<Podcast> podcasts)
		{
			this.deviceTree.contentTree.Nodes.Clear();
			this.inboxTree.contentTree.Nodes.Clear();
			this.subscriptionTree.contentTree.Nodes.Clear();
			
			this.inboxTree.contentTree.Nodes.Add(
			    "New", 
			    NavigationView.NewEpisodesImageIndex, 
			    NavigationView.NewEpisodes);

			this.inboxTree.contentTree.Nodes.Add(
			    "Downloads", 
			    NavigationView.DownloadedEpisodesImageIndex, 
			    NavigationView.DownloadedEpisodes);

			this.inboxTree.contentTree.ExpandAll();

			if (this.MediaPlayerConnected)
			{
				this.deviceTree.contentTree.Nodes.Add(
					this.MediaPlayerName,
					NavigationView.MediaPlayerImageIndex,
					NavigationView.MediaPlayer)
					.Add(
					"Content",
					NavigationView.MediaPlayerContentImageIndex,
					NavigationView.MediaPlayerContent);
				this.deviceTree.contentTree.ExpandAll();
			}
			else
			{
				this.deviceTree.contentTree.Nodes.Add(
					"Nothing connected",
					NavigationView.MediaPlayerImageIndex,
					string.Empty);
			}

			var subcriptonNode = this.subscriptionTree.contentTree.Nodes.Add(
				"Subscriptions",
				NavigationView.PodcastImageIndex,
				NavigationView.Subscriptions);

			foreach (var p in podcasts)
			{
				subcriptonNode.Add(
					p.Name,
					NavigationView.PodcastImageIndex,
					p.DbKey);
			}

			this.subscriptionTree.contentTree.ExpandAll();
			this.subscriptionTree.contentTree.SelectedNode = subcriptonNode;
		}

		public void RefreshMediaPlayer(string name, bool connected)
		{
			this.MediaPlayerConnected = connected;
			this.MediaPlayerName = name;

			this.deviceTree.contentTree.Nodes.Clear();

			if (this.MediaPlayerConnected)
			{
				this.deviceTree.contentTree.Nodes.Add(
					this.MediaPlayerName,
					NavigationView.MediaPlayerImageIndex,
					NavigationView.MediaPlayer)
					.Add(
					"Content",
					NavigationView.MediaPlayerContentImageIndex,
					NavigationView.MediaPlayerContent);
				this.deviceTree.contentTree.ExpandAll();
			}
			else
			{
				this.deviceTree.contentTree.Nodes.Add(
					"Nothing connected",
					NavigationView.MediaPlayerImageIndex,
					string.Empty);
			}
		}

		public bool MediaPlayerConnected
		{
			get;
			set;
		}

		public string MediaPlayerName
		{
			get;
			set;
		}

		public NavigationState State
		{
			get;
			private set;
		}

		public enum NavigationState
		{
			Unknown,
			MediaPlayer,
			MediaContent,
			Subscription,
			Podcast
		}

		private void InitializeComponent()
		{
			this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
			this.deviceTree = new Pibby.Controls.HeadedTree();
			this.subscriptionTree = new Pibby.Controls.HeadedTree();
			this.inboxTree = new Pibby.Controls.HeadedTree();
			this.tableLayoutPanel1.SuspendLayout();
			this.SuspendLayout();
			// 
			// tableLayoutPanel1
			// 
			this.tableLayoutPanel1.ColumnCount = 1;
			this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
			this.tableLayoutPanel1.Controls.Add(this.inboxTree, 0, 1);
			this.tableLayoutPanel1.Controls.Add(this.deviceTree, 0, 0);
			this.tableLayoutPanel1.Controls.Add(this.subscriptionTree, 0, 2);
			this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
			this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0);
			this.tableLayoutPanel1.Name = "tableLayoutPanel1";
			this.tableLayoutPanel1.RowCount = 3;
			this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 44.91978F));
			this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 55.08022F));
			this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 292F));
			this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
			this.tableLayoutPanel1.Size = new System.Drawing.Size(572, 498);
			this.tableLayoutPanel1.TabIndex = 3;
			// 
			// deviceTree
			// 
			this.deviceTree.Dock = System.Windows.Forms.DockStyle.Fill;
			this.deviceTree.Location = new System.Drawing.Point(3, 3);
			this.deviceTree.Name = "deviceTree";
			this.deviceTree.Size = new System.Drawing.Size(566, 86);
			this.deviceTree.TabIndex = 1;
			// 
			// subscriptionTree
			// 
			this.subscriptionTree.Dock = System.Windows.Forms.DockStyle.Fill;
			this.subscriptionTree.Location = new System.Drawing.Point(3, 208);
			this.subscriptionTree.Name = "subscriptionTree";
			this.subscriptionTree.Size = new System.Drawing.Size(566, 287);
			this.subscriptionTree.TabIndex = 5;
			// 
			// inboxTree
			// 
			this.inboxTree.Dock = System.Windows.Forms.DockStyle.Fill;
			this.inboxTree.Location = new System.Drawing.Point(3, 95);
			this.inboxTree.Name = "inboxTree";
			this.inboxTree.Size = new System.Drawing.Size(566, 107);
			this.inboxTree.TabIndex = 6;
			// 
			// NavigationView
			// 
			this.Controls.Add(this.tableLayoutPanel1);
			this.Name = "NavigationView";
			this.Size = new System.Drawing.Size(572, 498);
			this.tableLayoutPanel1.ResumeLayout(false);
			this.ResumeLayout(false);

		}
	}

	public static class TreeNodeExtensions
	{
		public static bool NodeExists(this TreeNodeCollection nodes, string guid)
		{
			return nodes.Find(guid, true).Length != 0;
		}

		public static TreeNode Add(this TreeNodeCollection nodes, string text, int imageIndex, string guid)
		{
			var newNode = new TreeNode(text, imageIndex, imageIndex)
				{
					Name = guid,
					Tag = new NodeTag { Guid = guid, DbKey = 0 }
				};

			nodes.Add(newNode);

			return newNode;
		}

		public static TreeNode Add(this TreeNodeCollection nodes, string text, int imageIndex, int dbKey)
		{
			var newNode = new TreeNode(text, imageIndex, imageIndex)
			{
				Name = text,
				Tag = new NodeTag { Guid = string.Empty, DbKey = dbKey }
			};

			nodes.Add(newNode);

			return newNode;
		}

		public static TreeNode Add(this TreeNode parentNode, string text, int imageIndex, string guid)
		{
			return parentNode.Nodes.Add(text, imageIndex, guid);
		}

		public static TreeNode Add(this TreeNode parentNode, string text, int imageIndex, int dbKey)
		{
			return parentNode.Nodes.Add(text, imageIndex, dbKey);
		}

		public static void Remove(this TreeNodeCollection nodes, string guid)
		{
			var found = nodes.Find(guid, true);

			if (found.Length > 0)
			{
				nodes.RemoveByKey(guid);
			}
		}
	}

	class NodeTag
	{
		public string Guid { get; set; }
		public int DbKey { get; set; }
	}
}
